/*
 * Server.cpp
 *
 *      Author: smirnovaop
 */

#include "Server.h"
#include "Client.h"
#include "Message.h"

Server::Server() {
	dbg_msg(LOG_TRACE, "Constructor of class Server");
}
int Server::send(Message& msg, u_int32_t id){
	size_t n_client = clnts.size();
	int ret = 0;
	for(size_t i = 0; i < n_client; i++){
		if (ID(clnts[i]) == id){
			Client* client = (Client *)PTR(clnts[i]);
			ret = client->recv(msg);
		}
	}
	return ret;
}

int Server::recv(Message& msg){
	Client* client;
	Message* message = NULL;
	bool is_registered = false;
	size_t 	i;
	clients clients_id;
	size_t 	number_client = clnts.size();
	std::pair<Client*, u_int32_t> temp_pair;
	char error_msg[512];
	dbg_msg(LOG_TRACE, "Server::receive message");
	switch (msg.getType()) {
		case MESSAGE:
			dbg_msg(LOG_TRACE, "receive message");
			if (msg.getTo() > 0){
				// to specific user
				i = 0;
				while (i < number_client){
					if (ID(clnts[i]) == msg.getTo()){
						client = PTR(clnts[i]);
						client->recv(msg);
						return 0;
					}
					i++;
				}
				if (i >= number_client){
					dbg_msg(LOG_ERROR, "Error in sending message");
					sprintf(error_msg, "Client with id: %u is not registered", msg.getTo());
					dbg_msg(LOG_ERROR, error_msg);
					return -1;
				}
			}else{
				//to all users
				for (size_t i = 0; i < number_client; i++){
					client = PTR(clnts[i]);
					message = new Message(msg);
					client->recv(*message);
					delete message;
				}
			}
			break;
		case REGISTRATION:
			sprintf(error_msg, "Receive request to registration client with id: %u", msg.getClientId());
			dbg_msg(LOG_TRACE, error_msg);
			is_registered = false;
			for (i = 0; i < number_client; i++){
				if (ID(clnts[i]) == msg.getClientId()){
					is_registered  = true;
					break;
				}
			}
			if (is_registered){
				sprintf(error_msg, "Client with id is already registered: %u", msg.getClientId());
				dbg_msg(LOG_ERROR, error_msg);
			}else{
				temp_pair = std::make_pair((Client *) msg.getClientPtr(), msg.getClientId());
				clnts.push_back(temp_pair);
				//generate Response of Registration and send it.
				message = genRespReg();
				PTR(clnts.back())->recv(*message);
				delete message;
			}
			break;
		case GET_CLIENTS:
			sprintf(error_msg, "Receive request to get clients client with id: %u", msg.getClientId());
			dbg_msg(LOG_TRACE, error_msg);
			is_registered = false;
			for (i = 0; i < number_client; i++){
				if (ID(clnts[i]) == msg.getClientId()){
					is_registered  = true;
					break;
				}
			}
			if (!is_registered){
				// Client is not registered
				dbg_msg(LOG_ERROR, "Error in request to get clients: client is not registered");
				return -1;
			}else{
				for (i = 0; i < number_client; i++){
					if (ID(clnts[i]) != msg.getClientId()){
						clients_id.push_back(ID(clnts[i]));
					}else{
						clients_id.push_back(ID(clnts[i]));
						client = PTR(clnts[i]);
					}
				}
				message = genRespClients(clients_id);
				client->recv(*message);
				delete message;

			}
			break;
		case EXIT:
			sprintf(error_msg, "Receive request to exit from server client with id: %u", msg.getClientId());
			dbg_msg(LOG_TRACE, error_msg);
			is_registered = false;
			for (i = 0; i < number_client; i++){
				if (ID(clnts[i]) == msg.getClientId()){
					is_registered  = true;
					message = genRespUnreg();
					PTR(clnts[i])->recv(*message);
					PTR(clnts[i])->registered = false;
					clnts.erase(clnts.begin() + i);
					break;
				}
			}
			if (!is_registered){
				// Client is not registered
				dbg_msg(LOG_DEBUG, "Client is already not registered on server");
				return -1;
			};
			break;

		default:
			break;
	}
	return 0;
}

Server::~Server() {
	dbg_msg(LOG_TRACE, "Desctructor of class Server");
}

